home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / util / boot / snap_v2_0.lha / Snap / ATIE.c next >
C/C++ Source or Header  |  1995-09-04  |  8KB  |  368 lines

  1. /* atie.c -- Ascii To Input Event */
  2.  
  3. /* The contents of this file are copyright 1990, Mikael Karlsson.
  4.  * You may use these routines freely in non-commerical programs,
  5.  * provided that some notice of it's use is given in the program
  6.  * and/or documentation.
  7.  */
  8.  
  9. struct HalfMap
  10. {
  11.     UBYTE *KeyMapTypes;
  12.     ULONG *KeyMap;
  13.     UBYTE *Capsable;
  14.     UBYTE *Repeatable;
  15. };
  16.  
  17. struct DeadSpec
  18. {
  19.     UBYTE ds_Prev1DownCode;
  20.     UBYTE ds_Prev1DownQual;
  21.     UBYTE ds_Prev2DownCode;
  22.     UBYTE ds_Prev2DownQual;
  23. };
  24.  
  25. #define CONTROLBITS ( ( 1 << 5) | ( 1 << 6))
  26. #define KEYMAPSIZE  64
  27.  
  28. #define S IEQUALIFIER_LSHIFT
  29. #define A IEQUALIFIER_LALT
  30. #define C IEQUALIFIER_CONTROL
  31.  
  32. /* These tables can be found in RKM Libraries & Devices 1.3 */
  33.  
  34. WORD deadQuals[ 8][ 10] =
  35. {
  36.     {KC_NOQUAL, 1, 0},
  37.     {KCF_SHIFT, 2, 0, S},
  38.     {KCF_ALT, 2, 0, A},
  39.     {KCF_ALT + KCF_SHIFT, 4, 0, S, A, S + A},
  40.     {KCF_CONTROL, 2, 0, C},
  41.     {KCF_CONTROL + KCF_SHIFT, 4, 0, S, C, S + C},
  42.     {KCF_CONTROL + KCF_ALT, 4, 0, A, C, A + C},
  43.     {KCF_CONTROL + KCF_ALT + KCF_SHIFT, 8, 0, S, A, S + A, C, C + S, C + A, C + S + A}
  44. };
  45.  
  46. WORD normalQuals[ 8][ 6] =
  47. {
  48.     {KC_NOQUAL, 1, 0, 0, 0, 0},
  49.     {KCF_SHIFT, 2, 0, 0, S, 0},
  50.     {KCF_ALT, 2, 0, 0, A, 0},
  51.     {KCF_ALT + KCF_SHIFT, 4, S + A, A, S, 0},
  52.     {KCF_CONTROL, 2, 0, 0, C, 0},
  53.     {KCF_CONTROL + KCF_SHIFT, 4, C + S, C, S, 0},
  54.     {KCF_CONTROL + KCF_ALT, 4, C + A, C, A, 0},
  55.     {KCF_CONTROL + KCF_ALT + KCF_SHIFT, 4, S + A, A, S, 0}
  56. };
  57.  
  58. #define keytype 0
  59. #define combos 1
  60.  
  61. #undef S
  62. #undef A
  63. #undef C
  64.  
  65. STATIC WORD checkNormalQual( LONG *four_bytesp, UBYTE val, UWORD type, UWORD *qualp)
  66. {
  67.     register UBYTE *p = ( UBYTE *) four_bytesp;    /* codes held in long word  */
  68.     register WORD position;
  69.     register WORD i = normalQuals[ type][ combos];
  70.  
  71.     position = 4;
  72.  
  73.     while ( i--)
  74.     {
  75.         --position;
  76.         if ( p[ position] == val)
  77.         {
  78.             *qualp = normalQuals[ type][ position + 2];
  79.             return 1;
  80.         }
  81.     }
  82.     return 0;
  83. }
  84.  
  85. WORD checkNormal( UBYTE *p, UBYTE val, WORD type, UWORD *qualp)
  86. {
  87.     /* only one way to match a vanilla control key  */
  88.     if ( type == KC_VANILLA && ( val & CONTROLBITS) == NULL)
  89.     {            /* control vanilla */
  90.         if ( checkNormalQual(
  91.             ( LONG *)p,
  92.             val | CONTROLBITS,
  93.             type, qualp))
  94.         {
  95.             *qualp |= IEQUALIFIER_CONTROL;
  96.             return ( 1);
  97.         }
  98.         else
  99.         {
  100.             return ( 0);
  101.         }
  102.     }
  103.     else
  104.     {            /* not a control */
  105.         return ( checkNormalQual( (LONG *)p, val, type, qualp));
  106.     }
  107. }
  108.  
  109.  
  110. STATIC WORD checkDead( UBYTE *keybase, UBYTE val, WORD type, UWORD *qualp, ULONG *indexp)
  111. {
  112.     WORD i;
  113.     WORD j;
  114.     register UBYTE *p = keybase;    /* need to remember keybase for offsets */
  115.     UBYTE *deadp;
  116.  
  117.     /* walk through two-byte entries, one for each qual. combo.       */
  118.     for ( i = 0; i < deadQuals[ type][ combos]; ++i, p += 2)
  119.     {
  120.         switch ( p[ 0])
  121.         {
  122.         case DPF_DEAD:    /* dead keys do not themselves map to anything */
  123.             break;
  124.         case DPF_MOD:    /* dead key modifiable  */
  125.             deadp = keybase + p[ 1];
  126.             /* look down the string indexed by dead-key     index */
  127.             for ( j = 0; j < 6; ++j)
  128.             {
  129.                 if ( deadp[ j] == val)
  130.                 {
  131.                     *qualp = deadQuals[ type][ i + 2];
  132.                     *indexp = j;
  133.                     return 1;
  134.                 }
  135.             }
  136.             break;
  137.         case 0:    /* normal stroke for this key   */
  138.             if ( p[ 1] == val)
  139.             {
  140.                 *qualp = deadQuals[ type][ i + 2];
  141.                 return 1;
  142.             }
  143.         }
  144.     }
  145.     return ( 0);
  146. }
  147.  
  148. /*
  149.  * Calculates Code+Qual of previous dead key ( should be keys)
  150.  * and puts them in DeapSpec.
  151.  * returns success ( 1) or failure ( 0).
  152.  */
  153. STATIC WORD BuildDeadSpec( ULONG inx, struct HalfMap *hm, WORD hms, struct DeadSpec *ds)
  154. {
  155.     /* find keystroke which generates index */
  156.  
  157.     register WORD code = 0;
  158.     register UBYTE *deadthing;
  159.     register WORD i;
  160.  
  161.     do
  162.     {
  163.         /* check each deadkey in the table      */
  164.  
  165.         if ( hm->KeyMapTypes[ code] & KCF_DEAD)
  166.         {
  167.             register WORD type = hm->KeyMapTypes[ code] & 7;
  168.  
  169.             /* keymap entry is pointer to prefix:byte pairs   */
  170.  
  171.             deadthing = ( UBYTE *) hm->KeyMap[ code];
  172.             for ( i = 0; i < deadQuals[ type][ combos]; ++i, deadthing += 2)
  173.             {
  174.                 /* check for index prefix and correct index     */
  175.                 if ( deadthing[ 0] == DPF_DEAD &&
  176.                     ( deadthing[ 1] & DP_2DINDEXMASK) == inx)
  177.                 {
  178.                     ds->ds_Prev1DownCode = code;
  179.                     ds->ds_Prev1DownQual = deadQuals[ type][ i + 2];
  180.                     ds->ds_Prev2DownCode = 0;
  181.                     ds->ds_Prev2DownQual = 0;
  182.                     return 1;
  183.                 }
  184.             }
  185.         }
  186.     }
  187.     while ( ++code < hms);
  188.  
  189.     return 0;        /* Not found */
  190. }
  191.  
  192. STATIC WORD checkString( UBYTE *keybase, UBYTE val, WORD type, UWORD *qualp)
  193. {
  194.     WORD i;
  195.     register UBYTE *p = keybase;    /* need to remember keybase for offsets */
  196.  
  197.     /* walk through two-byte entries, one for each qual. combo.       */
  198.     for ( i = 0; i < deadQuals[ type][ combos]; ++i, p += 2)
  199.     {
  200.         if ( p[ 0] == 1)
  201.         {        /* One char in string */
  202.             if ( keybase[ p[ 1]] == val)
  203.             {    /* Our char? */
  204.                 *qualp = deadQuals[ type][ i + 2];
  205.                 return 1;
  206.             }
  207.         }
  208.     }
  209.     return ( 0);
  210. }
  211.  
  212. /* BuildEvent tries to generate an input event.
  213.  * returns success ( 1) or failure ( 0).
  214.  */
  215. STATIC UWORD BuildEvent( register UBYTE value, struct HalfMap *hm, WORD hms, struct InputEvent *ie,
  216.     struct KeyMap *km)    /* We need this to find dead prefix */
  217. {
  218.     register UWORD code = 0;
  219.     register WORD type;
  220.     register LONG *p;    /* points to four-byte lokeymap entry   */
  221.     UWORD *qualp = &ie->ie_Qualifier;
  222.     WORD found_it = 0;
  223.     ULONG index = 0;
  224.  
  225.     p = ( LONG *) hm->KeyMap;
  226.  
  227.     do
  228.     {
  229.         type = hm->KeyMapTypes[ code];
  230.         /* determine type of key        */
  231.         if ( type & KCF_STRING)
  232.         {
  233.             found_it = checkString( ( UBYTE *) * p, value, type & 7, qualp);
  234.         }
  235.         else if ( type & KCF_DEAD)
  236.         {
  237.             found_it = checkDead( ( UBYTE *) * p, value, type & 7, qualp, &index);
  238.         }
  239.         else if ( !( type & KCF_NOP))
  240.         {
  241.             found_it = checkNormal( ( UBYTE *)p, value, type & 7, qualp);
  242.         }
  243.         ++p;
  244.     }
  245.     while ( !found_it && ++code < hms);
  246.  
  247.     if ( found_it)
  248.     {
  249.         ie->ie_Code = code;
  250.         /* Successful BuildEvent. Check for dead key. */
  251.         if ( index)
  252.         {
  253.             struct HalfMap *dhm;
  254.             struct DeadSpec *ds = ( struct DeadSpec *)&ie->ie_EventAddress;
  255.  
  256.             dhm = ( struct HalfMap *)&km->km_LoKeyMapTypes;
  257.             if ( BuildDeadSpec( index, dhm, 64, ds))
  258.             {
  259.                 return 1;
  260.             }
  261.             dhm = ( struct HalfMap *)&km->km_HiKeyMapTypes;
  262.             if ( BuildDeadSpec( index, dhm, 56, ds))
  263.             {
  264.                 return 1;
  265.             }
  266.             return 0;    /* Couldn't find index generating dead key */
  267.         }
  268.         else
  269.         {
  270.             return 1;
  271.         }
  272.     }
  273.     else
  274.     {
  275.         return 0;
  276.     }
  277. }
  278.  
  279. /*
  280.  * NAME
  281.  *      AsciiToInputEvent -- build input event to generate ascii
  282.  *
  283.  * SYNOPSIS
  284.  *      success = AsciiToInputEvent( ascii, inputevent, keymap)
  285.  *      ULONG AsciiToInputEvent( ULONG, struct InputEvent *, struct KeyMap *)
  286.  *
  287.  * FUNCTION
  288.  *      This function tries to generate an input event that, when sent
  289.  *      to the input handler, will generate the specified ascii code.
  290.  *
  291.  * INPUTS
  292.  *      ascii - the ascii code to be generated by the constructed
  293.  *              input event.
  294.  *
  295.  *      inputevent - the input event that will be filled will the
  296.  *              appropriate values to generate the given ascii code.
  297.  *
  298.  *      keymap - the keymap that the input event will be reverse-
  299.  *              engineered from.
  300.  *
  301.  *
  302.  * RESULT
  303.  *      success - a boolean value indicating whether the reverse-
  304.  *              engineering was successful.
  305.  *
  306.  * NOTE
  307.  *      The ascii code must be available in the given keymap to be
  308.  *      generatable. Ascii values between 128 and 160 are usually
  309.  *      not available with normal keymaps.
  310.  *
  311.  * SEE ALSO
  312.  *      RawKeyConvert( ), V36 keymap.library/MapANSI( ).
  313.  */
  314.  
  315. ULONG AsciiToInputEvent(  ULONG ascii, register struct InputEvent *ie, struct KeyMap *km)
  316. {
  317.     struct HalfMap *hm;
  318.  
  319.     ie->ie_Class = IECLASS_RAWKEY;
  320.     ie->ie_Qualifier = 0;
  321.     ie->ie_EventAddress = 0;
  322.  
  323.     /* Some ascii values has to be treated separately
  324.        since some programs know the difference between
  325.        for example CTRL-M and RETURN.  */
  326.     {
  327.         WORD code = 0;
  328.  
  329.         switch ( ascii)
  330.         {
  331.         case 0x08:    /* backspace  */
  332.             code = 0x41;
  333.             break;
  334.         case '\t':    /* tab        */
  335.             code = 0x42;
  336.             break;
  337.         case 0x0D:    /* return     */
  338.             code = 0x44;
  339.             break;
  340.         case 0x1B:    /* esc        */
  341.             code = 0x45;
  342.             break;
  343.         case 0x7F:    /* del        */
  344.             code = 0x46;
  345.             break;
  346.         }
  347.  
  348.         if ( code)
  349.         {
  350.             ie->ie_Code = code;
  351.             return 1;
  352.         }
  353.     }
  354.  
  355.     hm = ( struct HalfMap *)&km->km_LoKeyMapTypes;
  356.     if ( BuildEvent( ( UBYTE) ascii, hm, 64, ie, km))
  357.     {
  358.         return 1;    /* Key found in LoKeyMap */
  359.     }
  360.     hm = ( struct HalfMap *)&km->km_HiKeyMapTypes;
  361.     if ( BuildEvent( ( UBYTE) ascii, hm, 56, ie, km))
  362.     {
  363.         ie->ie_Code += 64;    /* Don't forget that we're in the hi keymap */
  364.         return 1;    /* Key found in HiKeyMap */
  365.     }
  366.     return 0;        /* No luck */
  367. }
  368.